/*
 * Proto Streamer
 * Copyright (C) 2009 John Pritchard.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 */
package p.c.http;

import p.c.Headers;
import p.c.Input;

import java.net.URL;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

/**
 * @author jdp
 */
public final class Response 
    extends Object
{
    public static class Input
        extends p.c.Input
    {
        private Connection connection;

        Input(Connection connection) throws IOException {
            super(connection.openInputStream());
            this.connection = connection;
        }

        public void close() throws IOException {
            try {
                super.close();
            }
            finally {
                this.connection.disconnect();
            }
        }
    }

    private Connection connection;
    private Request request;
    private Input in;
    private String responseline, protocol, message;
    private int status;
    private Headers headers;


    public Response(Connection connection)
        throws IOException
    {
        super();
        this.connection = connection;
        this.request = connection.getRequest();
        this.request.getOutputStream();
        this.headers = new Headers();
    }

    
    public InputStream getInputStream() throws IOException {
        Input in = this.in;
        if (null == in){
            in = new Response.Input(this.connection);
            this.in = in;
            this.responseline = in.readLine();
            java.lang.String[] response = this.responseline.split(" ");
            if (null != response){
                switch(response.length){
                case 2:
                    this.protocol = response[0];
                    this.status   = java.lang.Integer.parseInt(response[1]);
                    break;
                default:
                    if (3 <= response.length){
                        this.protocol = response[0];
                        this.status   = java.lang.Integer.parseInt(response[1]);
                        this.message  = Join(response,2,' ');
                        break;
                    }
                    else
                        throw new IllegalStateException("Bad response line '"+this.responseline+"' ["+(response.length)+"].");
                }
            }
            else
                throw new IllegalStateException("Bad response line '"+this.responseline+"'.");
                
            this.headers.read(in);
        }
        if (this.isOk())
            return in;
        else
            throw new IOException(this.responseline);
    }
    public boolean isOk(){
        switch (this.status){
        case 200:
        case 201:
        case 202:
        case 203:
        case 204:
            return true;
        default:
            return false;
        }
    }
    public boolean isNotOk(){
        switch (this.status){
        case 200:
        case 201:
        case 202:
        case 203:
        case 204:
            return false;
        default:
            return true;
        }
    }
    public String getProtocol(){
        return this.protocol;
    }
    public String getProtocolScheme(){
        String protocol = this.protocol;
        if (null != protocol){
            int idx = protocol.indexOf('/');
            if (0 < idx){
                return protocol.substring(0,idx).toLowerCase();
            }
        }
        return "http";
    }
    public String getMessage(){
        return this.message;
    }
    public int getStatus(){
        return this.status;
    }
    public String getResponseline(){
        return this.responseline;
    }
    public String getHeader(String name){
        return this.headers.valueOf(name);
    }
    public String getConnection(){
        return this.headers.valueOf("Connection");
    }
    public String getLocation(){
        return this.headers.valueOf("Location");
    }
    public boolean hasContentLength(){
        return this.headers.contains("Content-Length");
    }
    public boolean hasNotContentLength(){
        return this.headers.containsNot("Content-Length");
    }
    public int getContentLength(){
        java.lang.String string = this.headers.valueOf("Content-Length");
        if (null == string)
            return 0;
        else
            return java.lang.Integer.parseInt(string);
    }
    public java.lang.String getContentType(){
        return this.headers.valueOf("Content-Type");
    }
    public final static String Join(String[] list, int idx, char sep){
        StringBuilder strbuf = new StringBuilder();
        for (int cc = idx, count = list.length; cc < count; cc++){
            if (idx < cc)
                strbuf.append(sep);
            strbuf.append(list[cc]);
        }
        return strbuf.toString();
    }
}
